/*	Copyright (C) 2012  Claude Richard
 *
 *	Optimist Racing is free software: you can redistribute it and/or modify
 *	it under the terms of the GNU General Public License as published by
 *	the Free Software Foundation, either version 3 of the License, or
 *	(at your option) any later version.
 *
 *	Optimist Racing is distributed in the hope that it will be useful,
 *	but WITHOUT ANY WARRANTY; without even the implied warranty of
 *	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *	GNU General Public License for more details.
 *
 *	You should have received a copy of the GNU General Public License
 *	along with Optimist Racing.  If not, see <http://www.gnu.org/licenses/>.
 */

#include "Keyboard.hpp"

#include <fstream>
#include <allegro5\allegro5.h>
#include <GL\freeglut.h>

#define GLUT_KEY_MAX 256
#define GLUT_SPECIAL_KEY_MAX 256

cmKeyManager::cmKeyManager()
{

	// Initialize the 3 main arrays for buttons.
	m_times_pressed = new int[ BUTTON_NUM ];
	m_times_released = new int[ BUTTON_NUM ];
	m_pressed = new bool[ BUTTON_NUM ];
	for (int i = 0; i < BUTTON_NUM; i ++) {
		m_times_pressed[ i ] = 0;
		m_times_released[ i ] = 0;
		m_pressed[ i ] = false;
	}
	
	// Initialize the map array
	m_key_map = new unsigned char[ GLUT_KEY_MAX ];
	for ( int i = 0; i < GLUT_KEY_MAX; i ++ )
	{
		m_key_map[ i ] = BUTTON_NOTHING;
	}
	m_special_key_map = new int[ GLUT_SPECIAL_KEY_MAX ];
	for ( int i = 0; i < GLUT_SPECIAL_KEY_MAX; i ++ )
	{
		m_special_key_map[ i ] = BUTTON_NOTHING;
	}

	// Set the map array to these defaults.
	m_special_key_map[ GLUT_KEY_LEFT ] = BUTTON_SKID_LEFT;
	m_special_key_map[ GLUT_KEY_RIGHT ] = BUTTON_SKID_RIGHT;
	m_key_map[ 'a' ] = BUTTON_TURN_LEFT;
	m_key_map[ 'd' ] = BUTTON_TURN_RIGHT;
	m_special_key_map[ GLUT_KEY_UP ] = BUTTON_UP;
	m_special_key_map[ GLUT_KEY_DOWN ] = BUTTON_DOWN;

}

cmKeyManager::~cmKeyManager()
{
	// Delete the arrays in this object.
	delete[] m_times_pressed;
	delete[] m_times_released;
	delete[] m_pressed;
	delete[] m_key_map;
	delete[] m_special_key_map;
}

void cmKeyManager::set_mapping( unsigned char key, E_BUTTON button )
{
	m_key_map[ button ] = key;
}

void cmKeyManager::set_special_mapping( int key, E_BUTTON button )
{
	m_special_key_map[ button ] = key;
}

//void cmKeyManager::load_mappings( const char* filename )
//{
//
//	// Open the controls file.
//	std::ifstream infile( filename );
//
//	try
//	{
//		// Read in the controls.
//		for ( int i = 0; i < ALLEGRO_KEY_MAX; i ++ )
//		{
//			infile >> m_key_map[ i ];
//		}
//	} catch (std::exception e) {
//		// Something went wrong.
//		OutputDebugString( "Something went wrong while loading controls:" );
//		OutputDebugString( e.what() );
//		throw -1;
//	}
//
//	// Close the file.
//	infile.close();
//}

//void cmKeyManager::save_mappings( const char* filename ) const
//{
//
//	// Open the controls file.
//	std::ofstream outfile( filename );
//
//	try
//	{
//		// Write out the controls.
//		for ( int i = 0; i < ALLEGRO_KEY_MAX; i ++ )
//		{
//			outfile << m_key_map[ i ];
//		}
//	} catch (std::exception e) {
//		// Something went wrong.
//		OutputDebugString( "Something went wrong while saving controls:" );
//		OutputDebugString( e.what() );
//		throw -1;
//	}
//
//	// Close the file.
//	outfile.close();
//}

void cmKeyManager::press_key(unsigned char key)
{
	m_pressed[ m_key_map[key] ] = true;
	m_times_pressed[ m_key_map[key] ] ++;
}

void cmKeyManager::press_special_key(int key)
{
	m_pressed[ m_special_key_map[key] ] = true;
	m_times_pressed[ m_special_key_map[key] ] ++;
}

void cmKeyManager::release_key(unsigned char key)
{
	m_pressed[ m_key_map[key] ] = false;
	m_times_released[ m_key_map[key] ] ++;

}

void cmKeyManager::release_special_key(int key)
{
	m_pressed[ m_special_key_map[key] ] = false;
	m_times_released[ m_special_key_map[key] ] ++;
}

void cmKeyManager::reset_counts()
{
	for (int i = 0; i < BUTTON_NUM; i ++ ) {
		m_times_released[ i ] = 0;
		m_times_pressed[ i ] = 0;
	}
}

int cmKeyManager::times_pressed( E_BUTTON button ) const
{
	return m_times_pressed[ button ];
}

int cmKeyManager::times_released( E_BUTTON button ) const
{
	return m_times_released[ button ];
}

bool cmKeyManager::is_pressed( E_BUTTON button ) const
{
	return m_pressed[ button ];
}



KeyboardInputs::KeyboardInputs()
{
	mKeyTimesPressed = new int[ ALLEGRO_KEY_MAX ];
	mKeyTimesReleased = new int[ ALLEGRO_KEY_MAX ];
	mKeyPressed = new bool[ ALLEGRO_KEY_MAX ];
	mButtonTimesPressed = new int[ BUTTON_NUM ];
	mButtonTimesReleased = new int[ BUTTON_NUM ];
	mButtonPressed = new bool[ BUTTON_NUM ];
	mMap = new E_BUTTON[ ALLEGRO_KEY_MAX ];
	for (int i=0; i<ALLEGRO_KEY_MAX; i++) {
		mKeyTimesPressed[ i ] = 0;
		mKeyTimesReleased[ i ] = 0;
		mKeyPressed[ i ] = false;
		mMap[ i ] = BUTTON_NOTHING;
	}
	for (int i=0; i<BUTTON_NUM; i++) {
		mButtonTimesPressed[ i ] = 0;
		mButtonTimesReleased[ i ] = 0;
		mButtonPressed[ i ] = false;
	}

	// set default map
	mMap[ ALLEGRO_KEY_UP ] = BUTTON_UP;
	mMap[ ALLEGRO_KEY_DOWN ] = BUTTON_DOWN;
	mMap[ ALLEGRO_KEY_RIGHT ] = BUTTON_SKID_RIGHT;
	mMap[ ALLEGRO_KEY_LEFT ] = BUTTON_SKID_LEFT;
}

KeyboardInputs::~KeyboardInputs()
{
	delete mKeyTimesPressed;
	delete mKeyTimesReleased;
	delete mKeyPressed;
	delete mButtonTimesPressed;
	delete mButtonTimesReleased;
	delete mButtonPressed;
	delete mMap;
}

void KeyboardInputs::setMap( int key, E_BUTTON keytype )
{
	mMap[key] = keytype;
}

void KeyboardInputs::pressKey( int key )
{
	mKeyPressed[ key ] = true;
	mButtonPressed[ mMap[key] ] = true;
	mKeyTimesPressed[ key ] ++;
	mButtonTimesPressed[ mMap[key] ] ++;
}

void KeyboardInputs::releaseKey( int key )
{
	mKeyPressed[ key ] = false;
	mButtonPressed[ mMap[key] ] = false;
	mKeyTimesReleased[ key ] ++;
	mButtonTimesReleased[ mMap[key] ] ++;
}

void KeyboardInputs::resetCounts()
{
	for (int i=0; i<ALLEGRO_KEY_MAX; i++) {
		mKeyTimesPressed[ i ] = 0;
		mKeyTimesReleased[ i ] = 0;
	}
	for (int i=0; i<BUTTON_NUM; i++) {
		mButtonTimesPressed[ i ] = 0;
		mButtonTimesReleased[ i ] = 0;
	}
}

int KeyboardInputs::getKeyTimesPressed( int key ) const
{
	return mKeyTimesPressed[key];
}

int KeyboardInputs::getKeyTimesReleased( int key ) const
{
	return mKeyTimesReleased[key];
}

bool KeyboardInputs::isKeyPressed( int key ) const
{
	return mKeyPressed[key];
}

int KeyboardInputs::getButtonTimesPressed( E_BUTTON button ) const
{
	return mButtonTimesPressed[button];
}

int KeyboardInputs::getButtonTimesReleased( E_BUTTON button ) const
{
	return mButtonTimesReleased[button];
}

bool KeyboardInputs::isButtonPressed( E_BUTTON button ) const
{
	return mButtonPressed[button];
}